package hos.okhttp.http;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;

import hos.http.HttpApply;
import hos.http.HttpTag;
import hos.http.HttpUtils;
import hos.http.Progress;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

/**
 * <p>Title: ProgressResponseBody </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @version : 1.0
 * @date : 2023-02-24 19:17
 */
public class ProgressResponseBody extends ResponseBody {
    private final HttpTag.DownloadListeners mProgressListeners;

    private final ResponseBody body;
    private final Progress progress;

    private long contentLength;
    private BufferedSource bufferedSource;

    private final HttpApply<ResponseBody> mFinish;
    public ProgressResponseBody(HttpTag.DownloadListeners mProgressListeners, ResponseBody body) {
        this(mProgressListeners, body, null);
    }

    public ProgressResponseBody(HttpTag.DownloadListeners mProgressListeners, ResponseBody body, HttpApply<ResponseBody> mFinish) {
        this.mProgressListeners = mProgressListeners;
        this.body = body;
        this.mFinish = mFinish;
        progress = new Progress();
    }

    private long getContentLength() {
        if (contentLength == 0L) {
            contentLength = body.contentLength();
        }
        return contentLength;
    }

    private BufferedSource getBufferedSource() {
        if (bufferedSource == null) {
            bufferedSource = Okio.buffer(new ProgressSource(body.source()));
        }
        return bufferedSource;
    }

    @Override
    public long contentLength() {
        return getContentLength();
    }

    @Nullable
    @Override
    public MediaType contentType() {
        return body.contentType();
    }

    @NotNull
    @Override
    public BufferedSource source() {
        return getBufferedSource();
    }

    class ProgressSource extends ForwardingSource {
        Long readByteCount = 0L;

        public ProgressSource(@NotNull Source delegate) {
            super(delegate);
        }

        @Override
        public long read(@NotNull Buffer sink, long byteCount) throws IOException {
            try {
                long bytesRead = super.read(sink, byteCount);
                HttpUtils.progressResponseBody(mProgressListeners, progress, getContentLength(), readByteCount, bytesRead);
//                readByteCount += (bytesRead != -1L) ? bytesRead : 0;
//                if (mProgressListeners != null) {
//                    long currentElapsedTime = SystemClock.elapsedRealtime();
//                    long contentLength = getContentLength();
//                    for (ProgressListener listener : mProgressListeners) {
//                        listener.intervalByteCount += (bytesRead != -1L) ? bytesRead : 0;
//                        long currentInterval = currentElapsedTime - listener.elapsedTime;
//                        if (!progress.finish && (readByteCount == contentLength || bytesRead == -1L || currentInterval >= listener.interval)) {
//                            if (readByteCount == contentLength || bytesRead == -1L) {
//                                progress.finish = true;
//                            }
//                            progress.currentByteCount = readByteCount;
//                            progress.totalByteCount = contentLength;
//                            progress.intervalByteCount = listener.intervalByteCount;
//                            progress.intervalTime = currentInterval;
//                            listener.onProgress(progress);
//                            listener.elapsedTime = currentElapsedTime;
//                            listener.intervalByteCount = 0L;
//                        }
//                    }
//                }
                if (bytesRead == -1L) {
                    if (mFinish != null) {
                        mFinish.apply(ProgressResponseBody.this);
                    }
                }
                return bytesRead;
            } catch (Exception e) {
                if (mFinish != null) {
                    mFinish.apply(ProgressResponseBody.this);
                }
                throw e;
            }
        }
    }
}
